package czk.concrent.enjoyModelWithNotLock.atomicInterger;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author:ChenZhangKun
 * @Date: 2020/6/9 22:37
 */
public class AtomicIntegerTest {
    public static void main(String[] args) {
        SafeAccount safeAccount=new SafeAccount(100000);
        long l = System.currentTimeMillis();
        Account.demo(safeAccount);
        System.out.println(safeAccount.getBalance());
        System.out.println(System.currentTimeMillis() - l);
        // syn
        SynCount synCount=new SynCount(100000);
        long l1 = System.currentTimeMillis();
        Account.demo(synCount);
        System.out.println(synCount.getBalance());
        System.out.println(System.currentTimeMillis()-l1);
    }
}
class SafeAccount implements Account{
    // 原子性integer
    private AtomicInteger balance;

    public SafeAccount(Integer balance) {
        this.balance = new AtomicInteger(balance);
    }

    @Override
    public int getBalance() {
        return this.balance.get();
    }

    @Override
    public void withDraw(Integer count) {
        while (true){
            int pre=this.balance.get();
            int next=pre-count;
            // 以上是线程内完成的，并没有同步到主存
            // 同步到主存
            if (balance.compareAndSet(pre,next)){
                break;
            };
        }
    }
}

interface Account{

    // 获取余额
    int getBalance();
    // 取款
    void withDraw(Integer count);
    static void demo(Account account){
        // 创建1000个线程
        // 接收集合
        List<Thread> listThread=new ArrayList<>(1000);
        for (int i = 0; i < 3; i++) {
            listThread.add(new Thread(()->{
                account.withDraw(25000);
            }));
        }
        // 启动线程
        for (Thread thread : listThread) {
            thread.start();
        }
        // 等待线程运行完毕
        for (Thread thread : listThread) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class SynCount implements Account{
    private int balance;

    public SynCount(int balance) {
        this.balance = balance;
    }

    @Override
    public int getBalance() {
        return this.balance;
    }

    @Override
    public void withDraw(Integer count) {
        synchronized (this){
            balance-=count;
        }
    }
}
